﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.ServiceModel;
using Amazon.PAAPI.WCF;
using System.Configuration;
using Prices = Amazon.PAAPI.WCF.Price;
using System.Data.SqlClient;
using System.Data.Linq;
using System.IO;
namespace Amazon.PAAPI
{
    class AmazonCategoryRequest
    {
        private object lockObject = new Object();
        private bool multiThreaded = false;
        private const int pages = 10;
        AWSECommerceServicePortTypeClient amazonClient;
        private AmazonCategory category;
        public AmazonCategory Category { get { return category; } set { category = value; } }
        public AmazonCategoryRequest() {  amazonClient = AmazonHelper.BuildAmazonClient();  }
        public AmazonCategoryRequest(AmazonCategory cat) : this() { category = cat;  }
        public AmazonCategoryRequest(AmazonCategory cat, bool multiTh) : this() 
        { 
            category = cat; multiThreaded = multiTh;      
        }

   
        private List<Item> products = new List<Item>();
        public void Run()
        {

            ExploreNode(category.BrowseNode,0);

        }

        private void ExploreNode(string root, int indent)
        {
            
           
            
                BrowseNodeLookupRequest request = new BrowseNodeLookupRequest();
                request.ResponseGroup = new string[] { "BrowseNodeInfo" };
                request.BrowseNodeId = new string[] { root };
                BrowseNodeLookup lookup = new BrowseNodeLookup();
                lookup.AssociateTag = ConfigurationManager.AppSettings["associateTag"];
                lookup.AWSAccessKeyId = ConfigurationManager.AppSettings["accessKeyId"];
                lookup.Request = new BrowseNodeLookupRequest[] { request };



                BrowseNodeLookupResponse response = amazonClient.BrowseNodeLookup(lookup);
                if (response != null)
                {
                    if (response.BrowseNodes[0].BrowseNode[0].Children != null)
                    {
                        foreach (BrowseNode node in response.BrowseNodes[0].BrowseNode[0].Children)
                        {
                            try
                            {
                                for (int i = 0; i < indent; i++) Console.Write("--");
                                Console.WriteLine(node.BrowseNodeId + " " + node.Name); //afisare 

                                ExploreNode(node.BrowseNodeId, indent + 2);
                            }
                            catch (ServerTooBusyException stbe)
                            {
                                FileStream fs = new FileStream("recovery.txt", FileMode.OpenOrCreate, FileAccess.Write);
                                StreamWriter sw = new StreamWriter(fs);
                                sw.WriteLine(DateTime.Now + ": halted at node " + root);
                                sw.Close();
                                Console.WriteLine("Too busy");
                                Thread.Sleep(new TimeSpan(0, 30, 0));
                            }
                            catch (Exception e)
                            {
                            }

                        }
                    }
                    else
                    {
                        
                            AmazonCategory c = new AmazonCategory(category.Name, response.BrowseNodes[0].BrowseNode[0].BrowseNodeId, indent);

                            if (multiThreaded == false)
                            {
                                DownloadProductsSingleThreaded(c);
                                if (products.Count > 500)
                                    submitProductsToDb(products);
                            }
                            else
                            {                               
                                ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadProductsMultiThreaded), c);
                            }
                        
                       
                        
                    }
                }
            
            
        }

        private void submitProductsToDb(IList<Item> list)
        {
            using (DataClassesDataContext db = new DataClassesDataContext())
            {
                foreach (Item item in list)
                {
                    try
                    {
                        Product newProd = AmazonHelper.BuildProduct(item);
                        Prices newPrice = new Prices();
                        newPrice.timestamp = DateTime.Now;
                        if (newProd != null)
                        {
                            Product oldProd = db.Products.FirstOrDefault<Product>(x => x.ISBN == newProd.ISBN || x.UPC == newProd.UPC);
                            if (oldProd == null) //nu exista in BD produsul asta
                            {
                                db.Products.InsertOnSubmit(newProd);
                                db.SubmitChanges(ConflictMode.FailOnFirstConflict);
                                newPrice.product_id = newProd.ID;
                                newPrice.site_id = 1; //Amazon
                                newPrice.price1 = double.Parse(item.ItemAttributes.ListPrice.Amount) / 100;
                                db.Prices.InsertOnSubmit(newPrice);
                                db.SubmitChanges(ConflictMode.FailOnFirstConflict);
                            }
                            else //exista si trec la pret
                            {
                                newPrice.product_id = oldProd.ID;
                                newPrice.site_id = 1;
                                newPrice.price1 = double.Parse(item.ItemAttributes.ListPrice.Amount) / 100;
                                oldProd.imageLarge = newProd.imageLarge;
                                oldProd.imageMedium = newProd.imageMedium;
                                oldProd.imageSmall = newProd.imageSmall;
                                oldProd.imageSwatch = newProd.imageSwatch;
                                oldProd.linkAmazon = newProd.linkAmazon; //updatez linkurile, cine stie
                                db.Prices.InsertOnSubmit(newPrice);
                                db.SubmitChanges(ConflictMode.FailOnFirstConflict);


                            }
                        }
                    }
                    catch (InvalidOperationException ioe)
                    {
                    }
                    catch (SqlException sqlEx)
                    {

                    }
                    catch (Exception e)
                    {

                    }
                }
            }
            if(!multiThreaded) products.Clear();
        }
        private void DownloadProductsSingleThreaded(object arg)
        {
            AmazonCategory cat = (AmazonCategory)arg;
            AWSECommerceServicePortTypeClient localAmazonClient = AmazonHelper.BuildAmazonClient();
            const int pages = 10;
            for (int i = 0; i < pages; i++)
            {
                try
                {
                    ItemSearchRequest request = AmazonHelper.BuildItemSearchRequest(cat, i + 1);
                    ItemSearch itemSearch = AmazonHelper.BuildItemSearch(request);
                    ItemSearchResponse response = localAmazonClient.ItemSearch(itemSearch);


                    if (AmazonHelper.IsResponseValid(response))
                        foreach (var item in response.Items[0].Item)
                        {

                            products.Add(item);
                        }
                    else break;

                }
                catch (ServerTooBusyException stbe)
                {
                    FileStream fs = new FileStream("recovery.txt", FileMode.OpenOrCreate, FileAccess.Write);
                    StreamWriter sw = new StreamWriter(fs);
                    sw.WriteLine(DateTime.Now + ": halted at node " + cat.BrowseNode);
                    sw.Close();
                    Console.WriteLine("Too busy");
                    Thread.Sleep(new TimeSpan(0, 30, 0));
                }
                catch (Exception e)
                {
                }
            }
        }
        private void DownloadProductsMultiThreaded(object arg)
        {
            AmazonCategory cat = (AmazonCategory)arg;
            AWSECommerceServicePortTypeClient localAmazonClient = AmazonHelper.BuildAmazonClient();
            
            List<Item> localList = new List<Item>();
            for (int i = 0; i < pages; i++)
            {
                try
                {
                    ItemSearchRequest request = AmazonHelper.BuildItemSearchRequest(cat, i + 1);
                    ItemSearch itemSearch = AmazonHelper.BuildItemSearch(request);
                    ItemSearchResponse response = localAmazonClient.ItemSearch(itemSearch);


                    if (AmazonHelper.IsResponseValid(response))
                        foreach (var item in response.Items[0].Item)
                        {
                            localList.Add(item);
                        }
                    else break;

                }
                catch (ServerTooBusyException stbe)
                {
                    FileStream fs = new FileStream("recovery.txt", FileMode.OpenOrCreate, FileAccess.Write);
                    StreamWriter sw = new StreamWriter(fs);
                    sw.WriteLine(DateTime.Now + ": halted at node " + cat.BrowseNode);
                    sw.Close();
                    Console.WriteLine("Too busy");
                    Thread.Sleep(new TimeSpan(0, 30, 0));
                }
                catch (Exception e)
                {

                }
            }
            submitProductsToDb(localList);
            
        }
    }

}
